#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include <QPainter>
#include "mypushbutton.h"
#include <QTimer>
#include <QSound>
#include "myblock.h"
#include <QTime>
#include <string.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->grabKeyboard();

    this->gameStart = 0; // 游戏运行标志
    memset(this->disTable, 0, sizeof(this->disTable));
    this->failure = 0;

    this->setFixedSize(350, 600); // 设置固定窗口大小
    this->setWindowIcon(QIcon(":/res/tiles5.png")); // 设置图标
    this->setWindowTitle("俄罗斯方块-King"); // 设置窗口标题

    /* 退出 */
    connect(ui->actionQuit, &QAction::triggered, this, [=](){
        this->close();
    });

    /* 帮助 */
    connect(ui->actionHelp, &QAction::triggered, this, [=](){
        QMessageBox * message = new QMessageBox(this);
        message->setModal(false);
        message->setWindowTitle("帮助");
        //message->setMinimumSize(QSize(300, 200)); // 不起作用
        message->setText("玩个俄罗斯方块还要帮助，MDZZ");
        message->show();
    });

    MyPushButton * startBtn = new MyPushButton(":/res/MenuSceneStartButton.png"); // 创建开始按钮
    startBtn->setParent(this); // 指定父类
    startBtn->move(this->width()*0.5 - startBtn->width()*0.5, this->height()*0.85); // 移动显示位置

    /* 准备背景音乐 */
    player = new QMediaPlayer;
    QMediaPlaylist * playlist = new QMediaPlaylist;
    player->setPlaylist(playlist);
    playlist->addMedia(QMediaContent(QUrl::fromLocalFile("../eluosi/res/bgm.wav")));
    playlist->setCurrentIndex(1);
    playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);

    /* 准备开始按钮音效 */
    QSound * startSound = new QSound(":/res/TapButtonSound.wav", this);

    MyBlock * block = new MyBlock; // 创建一个方块组
    block->newBlock();
    this->drawBlocks(block);

    /* 创建一个800ms定时器用于下降定时 */
    timer1 = new QTimer(this);
    timer1->setInterval(800);
    timer1->start();
    timer1->start();
    timer1->start();

    /* 监听开始按钮 */
    connect(startBtn, &MyPushButton::clicked, this, [=](){
        startSound->play(); // 播放开始按钮音效
        startBtn->zoomDown();
        startBtn->zoomUp();
        if(this->failure == 0)
        {
            this->gameStart = !this->gameStart;
            if(this->gameStart)
            {
                timer1->start();
                player->play(); // 播放游戏背景音乐
                connect(timer1, &QTimer::timeout, this, [=](){
                    this->dropBlocks(block);
                    update();
                });
                /* 下 */
                connect(this, &MainWindow::downKeyPressed, this, [=](){
                    this->dropBlocks(block);
                    update();
                });
                /* 左 */
                connect(this, &MainWindow::leftKeyPressed, this, [=](int a){
                    this->moveBlocks(block, a);
                    update();
                });
                /* 右 */
                connect(this, &MainWindow::rightKeyPressed, this, [=](int a){
                    this->moveBlocks(block, a);
                    update();
                });
                /* 空格 */
                connect(this, &MainWindow::blankKeyPressed, this, [=](){
                    this->changeBlocks(block);
                    update();
                });
            }
            else
            {
                player->stop();
                timer1->disconnect();
                disconnect(this, &MainWindow::downKeyPressed, 0, 0);
                disconnect(this, &MainWindow::leftKeyPressed, 0, 0);
                disconnect(this, &MainWindow::rightKeyPressed, 0, 0);
                disconnect(this, &MainWindow::blankKeyPressed, 0, 0);
                this->gameStart = 0;
            }
        }
        else
        {
            /* 失败了重新开始游戏 */
            this->failure = 0;
            timer1->disconnect();
            disconnect(this, &MainWindow::downKeyPressed, 0, 0);
            disconnect(this, &MainWindow::leftKeyPressed, 0, 0);
            disconnect(this, &MainWindow::rightKeyPressed, 0, 0);
            disconnect(this, &MainWindow::blankKeyPressed, 0, 0);
            memset(this->disTable, 0, sizeof(this->disTable));
            update();
            this->gameStart = 0;
            this->successLabel->move(this->width() - successLabel->width()*0.5, -successLabel->height()); //隐藏在上方

        }

    });

    /* 准备胜利音效 */
    QSound * winSound = new QSound(":/res/LevelWinSound.wav", this);

    /* 胜利图片 */
    this->successLabel = new QLabel(this);
    QPixmap successPix(":/res/LevelCompletedDialogBg.png");
    this->successLabel->setPixmap(successPix);
    this->successLabel->setGeometry(0,0,successPix.width(),successPix.height());
    this->successLabel->move(this->width() - successLabel->width()*0.5, -successLabel->height()); //隐藏在上方

    this->successAnimation = new QPropertyAnimation(successLabel, "geometry");
    this->successAnimation->setDuration(1000); // 设置时间间隔
    this->successAnimation->setStartValue(QRect(this->width()*0.5 - successLabel->width()*0.5, -successLabel->height(), successLabel->width(), successLabel->height())); // 设置起始值
    this->successAnimation->setEndValue(QRect(this->width()*0.5 - successLabel->width()*0.5, successLabel->y()+120, successLabel->width(), successLabel->height())); // 设置结束值
    this->successAnimation->setEasingCurve(QEasingCurve::OutBounce); // 设置缓和曲线（弹跳效果）

    /* 监听失败信号 */
    connect(this, &MainWindow::failed, this, [=](){
        winSound->play();
        /* 弹出胜利图片 */
        this->successAnimation->start(); // 启动动画
    });

}

MainWindow::~MainWindow()
{
    delete ui;
}

/* 填充disTable */
void MainWindow::drawBlocks(MyBlock * block)
{
    for(int i = 0; i < 4; i++)
    {
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].color = block->blocksColor;
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].dropping = 1;
    }
}



void MainWindow::dropBlocks(MyBlock * block)
{
    MyBlock * blockBac = new MyBlock;

    this->clearLine(); //

    for(int i = 0; i < 4; i++)
    {
        /* 判断是否到底部或者下方已有方块 */
        if(block->curBlockArr[i].x + 1 > 19 ||
          (this->disTable[block->curBlockArr[i].x+1][block->curBlockArr[i].y].dropping==0 &&
           this->disTable[block->curBlockArr[i].x+1][block->curBlockArr[i].y].color != 0))
        {
            for(int i = 0; i < 4; i++)
            {
              this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].dropping = 0;
            }
            for(int i = 0; i < 10; i++)
            {
                if((this->disTable[0][i].color&&this->disTable[0][i].dropping == 0) ||
                        (this->disTable[0][i].color && this->disTable[1][i].dropping == 0)||
                        (this->disTable[2][i].color&&this->disTable[2][i].dropping == 0))
                {
                    this->failure = 1;
                    timer1->disconnect();
                    this->player->stop();
                    emit this->failed();
                }
                else
                {
                   this->clearLine(); //
                   block->newBlock();
                }
            }
            return;
        }
    }
    memcpy(blockBac, block, sizeof(MyBlock)); // 数据备份到blockBac中
    /* 清空当前位置 */
    for(int i = 0; i < 4; i++)
    {
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].color = 0;
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].dropping = 0;
    }
    /* 写入数据到下一个位置 */
    for(int i = 0; i < 4; i++)
    {
        blockBac->curBlockArr[i].x += 1;
        this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].color = blockBac->blocksColor;
        this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].dropping = 1;
    }
    memcpy(block, blockBac, sizeof(MyBlock)); // 更新后数据重新拷贝回block中

    this->clearLine(); //
}

void MainWindow::moveBlocks(MyBlock * block, int move)
{
    MyBlock * blockBac = new MyBlock;
    for(int i = 0; i < 4; i++)
    {
        /* 判断左右是否已有方块 或者下方已有方块 */
        if(block->curBlockArr[i].y + move < 0 || block->curBlockArr[i].y + move > 9 ||
          (this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y + move].dropping ==0 &&
           this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y + move].color != 0))
        {
            return;
        }
    }
    memcpy(blockBac, block, sizeof(MyBlock)); // 数据备份到blockBac中
    /* 清空当前位置 */
    for(int i = 0; i < 4; i++)
    {
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].color = 0;
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].dropping = 0;
    }
    /* 写入数据到下一个位置 */
    for(int i = 0; i < 4; i++)
    {
        blockBac->curBlockArr[i].y += move;
        this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].color = blockBac->blocksColor;
        this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].dropping = 1;
    }
    memcpy(block, blockBac, sizeof(MyBlock)); // 更新后数据重新拷贝回block中

    this->clearLine(); //
}

void MainWindow::changeBlocks(MyBlock *block)
{
    if(block->blocksColor == 7) // 田字型不变换
        return;

    MyBlock * blockBac = new MyBlock;

    memcpy(blockBac, block, sizeof(MyBlock)); // 数据备份到blockBac中

    Point p = block->curBlockArr[1]; // 旋转中心

    for(int i = 0; i < 4; i++)
    {
        Point temp = block->curBlockArr[i];
        blockBac->curBlockArr[i].x = p.x - temp.y + p.y;
        blockBac->curBlockArr[i].y = temp.x - p.x + p.y;
    }

    for(int i = 0; i < 4; i++)
    {
        /* 判断左右是否已有方块 */
        if(blockBac->curBlockArr[i].y < 0 || blockBac->curBlockArr[i].y > 9 || blockBac->curBlockArr[i].x + 1 > 19 ||
          (this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].dropping ==0 &&
           this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].color != 0))
        {
            return;
        }
    }

    /* 清空当前位置 */
    for(int i = 0; i < 4; i++)
    {
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].color = 0;
        this->disTable[block->curBlockArr[i].x][block->curBlockArr[i].y].dropping = 0;
    }

    /* 写入数据到下一个位置 */
    for(int i = 0; i < 4; i++)
    {
        this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].color = blockBac->blocksColor;
        this->disTable[blockBac->curBlockArr[i].x][blockBac->curBlockArr[i].y].dropping = 1;
    }
    memcpy(block, blockBac, sizeof(MyBlock)); // 更新后数据重新拷贝回block中

    this->clearLine(); //
}

void MainWindow::clearLine()
{
    int k = 19; // 最后一行
    for(int i = 19; i > 0; i--)
    {
        int count = 0;
        for(int j = 0; j < 10; j++)
        {
            if(this->disTable[i][j].color !=0 && this->disTable[i][j].dropping == 0)
                count++;
            this->disTable[k][j] = this->disTable[i][j];
        }
        if(count < 10)
        {
            k--;
        }
    }
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    QPixmap pix;
    /* 背景图片 */
    pix.load(":/res/background.png");
    painter.drawPixmap(0, 0, this->width(), this->height(), pix);

    /* 画方块 */
    for(int i = 0; i < 20; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            if(this->disTable[i][j].color != 0)
            {
                pix.load(QString(":/res/tiles%1.png").arg(disTable[i][j].color));
                pix = pix.scaled(pix.width()*1.11, pix.height()*1.12);
                painter.drawPixmap(36+j*pix.width(), 85+i*pix.height(), pix.width(), pix.height(), pix);
            }
        }
    }

}


void MainWindow::keyPressEvent(QKeyEvent *ev)
{
    if(this->failure)
        return;
    if(ev->key() == 65 || ev->key() == 16777234) // "A" 或 "方向键-左"
    {
        emit this->leftKeyPressed(-1);
    }
    if(ev->key() == 68 || ev->key() == 16777236) // "D" 或 "方向键-右"
    {
        emit this->rightKeyPressed(1);
    }
    if(ev->key() == 83 || ev->key() == 16777237) // "A" 或 "方向键-下"
    {
        emit this->downKeyPressed();
    }
    if(ev->key() == 32) // "空格"
    {
        emit this->blankKeyPressed();
    }
    //qDebug() << ev->key();

    MainWindow::keyReleaseEvent(ev);
}

